package com.itheima;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.xml.parsers.SAXParser;
import java.io.*;
import java.net.Socket;
import java.util.*;

public class ChatServerThread extends Thread {
    private Socket socket;
    public ChatServerThread(Socket socket) {
        this.socket = socket;
    }
/*
         100: 表示登陆
         101: 表示注册

         200: 表示单聊
         201: 表示群聊
         202: 表示随机聊

         300: 客户端获取已上线的所有用户
         301: 客户端获取上线用户根据用户名升序排序
         302: 客户端获取指定性别的上线用户
 */

    //服务端主方法
    @Override
    public void run() {
        try {
            // 1.从socket中去获取当前客户端的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                // 读取客户端发送过来的消息
                String flag = br.readLine();
                // 对客户端的消息进行处理
                switch (flag) { // 100: 表示登陆
                    case "100":
                        doLogin(br);//登陆
                        break;
                    case "101":
                        doRegister(br);//注册
                        break;
                    case "200": // 200: 表示单聊
                        doSingleChat(br);
                        break;
                    case "201": // 201: 表示群聊
                        doAllChat(br);
                        break;
                    case "202":
                        doRandomChat(br);//随机聊
                        break;
                    case "300":
                        doShowAll(br);//显示所有
                        break;
                    case  "301":
                        doSortList(br);//按名字排序
                        break;
                    case "302"://302:表示筛选指定性别的上线用户
                        doSiftGender(br);
                        break;
                }
            }
        } catch (Exception e) {
            try {
                System.out.println("当前有人下线了！");
                // 从在线socket集合中移除本socket
                ChatServer.allSocketOnLine.remove(socket);
                // 发送在线用户给所有人
                String values = ChatServer.allSocketOnLine.values().toString();
                sendMsgToAllClient("有用户下线了，当前在线用户： " + values);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    // 登陆
    private void doLogin(BufferedReader br){
        // 登录消息: 用户登录发送过来的数据格式为:用户名,性别,年龄
        try {
            String userInfo = br.readLine();
            String[] split = userInfo.split(",");
            String userName = split[0];
            String sex = split[1];
            String ip = socket.getInetAddress().getHostAddress();
            int age = Integer.parseInt(split[2]);

            User user = new User(userName, sex, ip, age);

            if (ChatServer.allUsers.containsKey(userName)) {
                ChatServer.allSocketOnLine.put(socket, user);
                String values = userName + "用户登录了, 当前在线：" + ChatServer.allSocketOnLine.values().toString();
                sendMsgToAllClient(values);
            } else {
                sendMsgToMe(socket, "你输入用户不存在，请重新输入！");
            }
            System.out.println(ChatServer.allSocketOnLine);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //注册
    private void doRegister(BufferedReader br) {
        try {
            String userInfo = br.readLine();
            String[] split = userInfo.split(",");
            String userName = split[0];
            String sex = split[1];
            int age = Integer.parseInt(split[2]);
            String ip = socket.getInetAddress().getHostAddress();

            if (userName.matches("[A-Za-z0-9]{1}.{2,10}$")){
                User user = new User(userName, sex, ip, age);
                if (ChatServer.allUsers.containsKey(userName)) {
                    sendMsgToMe(socket, "已存在该用户，请重新输入正确的名字");
                } else {
                    ChatServer.allUsers.put(userName, user);
                    sendMsgToMe(socket, "注册成功");
                }
                System.out.println(ChatServer.allUsers);
            }else {
                sendMsgToMe(socket,"你输入的名字有误，请以字母或数字开头");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 单聊
    private void doSingleChat(BufferedReader br) throws Exception {
        // 私发消息
        // 获取对谁私发！
        String destName = br.readLine();
        // 获取私发消息
        String privateMsg = br.readLine();
        sendMsgToOneClient(destName, ChatServer.allSocketOnLine.get(socket).getUserName() + "对你说： " + privateMsg);
    }

    // 群聊
    private void doAllChat(BufferedReader br) throws Exception {
        if (ChatServer.admin.containsKey(ChatServer.allSocketOnLine.get(socket).getUserName())){
            // 群发消息
            String msg = br.readLine();
            // 群发消息给所有人
            sendMsgToAllClient(ChatServer.allSocketOnLine.get(socket).getUserName() + "对所有人说： " + msg);
        }else {
            sendMsgToMe(socket,"你不是管理员，不能群发信息！");
        }
    }

    //随机聊
    private void doRandomChat(BufferedReader br){
        try {
            String msg = br.readLine();
            Set<Map.Entry<Socket, User>> entries = ChatServer.allSocketOnLine.entrySet();
            ArrayList<Socket> socketsList = new ArrayList<>();
            for (Map.Entry<Socket, User> entry : entries) {
                if (entry.getKey() != socket) {
                    socketsList.add(entry.getKey());
                }
            }
            Random rand = new Random();
            int i = rand.nextInt(socketsList.size());
            Socket sk = socketsList.get(i);
            sendMsgToOneClient(ChatServer.allSocketOnLine.get(sk).getUserName(), ChatServer.allSocketOnLine.get(socket).getUserName() + "发给你了:" + msg);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //显示所有人
    private void doShowAll(BufferedReader br) {
        try {
            Set<Map.Entry<Socket, User>> entries = ChatServer.allSocketOnLine.entrySet();
            for (Map.Entry<Socket, User> entry : entries) {
                sendMsgToMe(socket, entry.toString());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //按名字排序
    private void doSortList(BufferedReader br){
        try {
            Set<Map.Entry<Socket, User>> entries = ChatServer.allSocketOnLine.entrySet();
            ArrayList<User> list = new ArrayList<>();
            for (Map.Entry<Socket, User> entry : entries) {
                list.add(entry.getValue());
            }
            list.sort(new Comparator<User>() {
                @Override
                public int compare(User o1, User o2) {
                    Character c1 = o1.getUserName().charAt(0);
                    Character c2 = o2.getUserName().charAt(0);
                    return c1 - c2;
                }
            });
            sendMsgToMe(socket, list.toString());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //筛选指定性别
    private void doSiftGender(BufferedReader bf) {
        try {
            String gender = bf.readLine();
            for (Socket sk : ChatServer.allSocketOnLine.keySet()) {
                User user = ChatServer.allSocketOnLine.get(sk);
                if (gender.equals(user.getSex())) {
                    sendMsgToMe(socket, "你指定的性别在线用户列表：" + user.toString());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    //群发信息
    private void sendMsgToAllClient(String msg)  {
        try {
            for (Socket sk : ChatServer.allSocketOnLine.keySet()) {
                PrintStream ps = new PrintStream(sk.getOutputStream());
                ps.println(msg);
                ps.flush();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //发送给某人
    private void sendMsgToOneClient(String destName, String privateMsg){
        try {
            for (Socket sk : ChatServer.allSocketOnLine.keySet()) {
                User user = ChatServer.allSocketOnLine.get(sk);
                if (user.getUserName().equals(destName)) {
                    PrintStream ps = new PrintStream(sk.getOutputStream());
                    ps.println(privateMsg);
                    ps.flush();
                    break;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //返还信息给自己
    private void sendMsgToMe(Socket socket,String msg){
        try{
            PrintStream ps = new PrintStream(socket.getOutputStream());
            ps.println(msg);
            ps.flush();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
